package com.lagou.rpc.server;

import com.lagou.rpc.entity.RpcRequest;
import com.lagou.rpc.entity.RpcResponse;
import com.lagou.rpc.spring.SpringContextHolder;
import com.lagou.rpc.zk.ZkClient;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;

/**
 * 服务端处理类，动态调用spring bean
 */
public class RpcNettyHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private final ZkClient zkClient;
    private final String url;
    RpcNettyHandler(ZkClient zkClient, String url) {
        this.zkClient = zkClient;
        this.url = url;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, RpcRequest request) {
        long start = System.currentTimeMillis();
        String beanName = request.getClassName();
        RpcResponse response = new RpcResponse();
        if (request.getRequestId() == null) {
            response.setError("requestId can not be null");
        } else {
            Object target = SpringContextHolder.getBean(beanName);
            Method[] m = target.getClass().getDeclaredMethods();
            try {
                String methodName = request.getMethodName();
                Optional<Method> optional = Arrays.stream(m)
                        .filter(item -> methodName.equals(item.getName())).findFirst();

                if (optional.isPresent()) {
                    Object result = optional.get().invoke(target, request.getParameters());
                    response.setData(result);
                    response.setRequestId(request.getRequestId());
                } else {
                    response.setError("no such method error");
                }
            } catch (Exception e) {
                e.printStackTrace();
                response.setError(e.toString());
            }
        }
        context.writeAndFlush(response).addListener(listener -> {
            long end = System.currentTimeMillis();
            long cost = end - start;
            String path = "/rpc/" + url + ".lastTime";
            if (zkClient.exists(path)) {
                zkClient.delete(path);
            }
            zkClient.create(path, String.valueOf(cost), true);
        });
    }
}
